package com.derbysoft.synxisadapter.dswitch3.translator;

import com.derbysoft.dswitch.dto.hotel.common.*;
import com.derbysoft.dswitch.dto.hotel.reservation.HotelReservationDTO;
import com.derbysoft.dswitch.dto.hotel.reservation.ReservationRoomStayDTO;
import com.derbysoft.dswitch.remote.hotel.dto.HotelReservationRequest;
import com.derbysoft.synxisadapter.commons.dto.synxis.*;
import com.derbysoft.synxisadapter.commons.model.Channel;
import com.derbysoft.synxisadapter.commons.utils.Constant;
import com.derbysoft.synxisadapter.dswitch2.translator.Translator;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * User: jason
 * Date: 2012-11-23
 */
@Component("ds3HotelResRQTranslator")
public class HotelResRQTranslator extends AbstractTranslator
        implements Translator<HotelReservationRequest, OTAHotelResRQ, Void> {

    private static final String CONFIRM_TYPE = "5";

    @Override
    public OTAHotelResRQ translate(HotelReservationRequest request, Void aVoid) {
        OTAHotelResRQ otaHotelResRQ = new OTAHotelResRQ();
        otaHotelResRQ.setPrimaryLangID(Constant.PRIMARY_LANG_ID);
        otaHotelResRQ.setPOS(translatePOS(request.getHeader().getSource()));
        otaHotelResRQ.setResStatus(Constant.RESERVATION_STATUS);
        Channel channel = loadChannel(request.getHeader().getSource());
        otaHotelResRQ.setHotelReservations(createDS3HotelReservation(channel, request.getHotelReservationRQ().getHotelReservation()));
        return otaHotelResRQ;
    }

    private ArrayOfHotelReservation createDS3HotelReservation(Channel channel, HotelReservationDTO ds3HotelReservation) {
        ArrayOfHotelReservation arrayOfHotelReservation = createArrayOfHotelReservation();
        HotelReservation hotelReservation = createHotelReservation();
        hotelReservation.setRoomStays(translateRoomStays(ds3HotelReservation));
        hotelReservation.setResGlobalInfo(translateResGlobalInfo(channel, ds3HotelReservation));
        hotelReservation.setResGuests(translateResGuests(ds3HotelReservation));
        arrayOfHotelReservation.getHotelReservation().add(hotelReservation);
        return arrayOfHotelReservation;
    }

    private ResGlobalInfo translateResGlobalInfo(Channel channel, HotelReservationDTO ds3HotelReservation) {
        ResGlobalInfo resGlobalInfo = createResGlobalInfo();
        ArrayOfProfileInfo arrayOfProfileInfo = createArrayOfProfileInfo();
        arrayOfProfileInfo.getProfileInfo().add(createProfileInfo(channel));
        resGlobalInfo.setProfiles(arrayOfProfileInfo);
        List<GuaranteeDTO> guaranteesList = ds3HotelReservation.getRoomStaysList().get(0).getGuaranteesList();
        if (CollectionUtils.isNotEmpty(guaranteesList)) {
            resGlobalInfo.setGuarantee(translateGuarantee(guaranteesList));
        }
        resGlobalInfo.setHotelReservationIDs(translateReservationIDs(channel.getId(), ds3HotelReservation.getChannelReservationNo()));
        resGlobalInfo.setComments(translateComments(ds3HotelReservation.getRoomStaysList().get(0)));
        return resGlobalInfo;
    }

    private ArrayOfComment translateComments(ReservationRoomStayDTO reservationRoomStayDTO) {
        ArrayOfComment arrayOfComment = createArrayOfComment();
        if (CollectionUtils.isNotEmpty(reservationRoomStayDTO.getCommentsList())) {
            StringBuilder builder = new StringBuilder();
            for (String comment : reservationRoomStayDTO.getCommentsList()) {
                builder.append(comment).append(" ");
            }
            Comment comment = createComment();
            comment.setText(builder.toString());
            arrayOfComment.getComment().add(comment);
        }

        if (CollectionUtils.isNotEmpty(reservationRoomStayDTO.getSpecialRequestsList())) {
            StringBuilder builder = new StringBuilder();
            for (String specialList : reservationRoomStayDTO.getSpecialRequestsList()) {
                builder.append(specialList).append(" ");
            }
            Comment comment = createComment();
            comment.setText(builder.toString());
            arrayOfComment.getComment().add(comment);
        }
        return arrayOfComment;
    }

    private ArrayOfHotelReservationID translateReservationIDs(String channelId, String channelReservationNo) {
        ArrayOfHotelReservationID arrayOfHotelReservationID = createArrayOfHotelReservationID();
        HotelReservationID hotelReservationID = createHotelReservationID();
        hotelReservationID.setResIDType(Constant.HOTEL_RES_ID_TYPE);
        hotelReservationID.setResIDSource(channelId);
        hotelReservationID.setResIDValue(channelReservationNo);
        arrayOfHotelReservationID.getHotelReservationID().add(hotelReservationID);
        return arrayOfHotelReservationID;
    }

    private Guarantee translateGuarantee(List<GuaranteeDTO> guaranteesList) {
        Guarantee guarantee = createGuarantee();
        ArrayOfGuaranteeAccepted arrayOfGuaranteeAccepted = createArrayOfGuaranteeAccepted();

        for (GuaranteeDTO guaranteeDTO : guaranteesList) {
            if (guaranteeDTO.getGuaranteeType() == GuaranteeDTO.GuaranteeType.CreditCard) {
                GuaranteeAccepted guaranteeAccepted = createGuaranteeAccepted();
                guaranteeAccepted.setPaymentCard(translatePaymentCard(guaranteeDTO.getPaymentCard()));
                arrayOfGuaranteeAccepted.getGuaranteeAccepted().add(guaranteeAccepted);
            }
        }
        guarantee.setGuaranteesAccepted(arrayOfGuaranteeAccepted);
        return guarantee;
    }

    private PaymentCard translatePaymentCard(PaymentCardDTO paymentCardDTO) {
        PaymentCard paymentCard = createPaymentCard();
        paymentCard.setCardCode(paymentCardDTO.getCardCode());
        paymentCard.setCardHolderName(paymentCardDTO.getCardHolderName());
        paymentCard.setExpireDate(paymentCardDTO.getExpireDate());
        paymentCard.setCardNumber(paymentCardDTO.getCardNumber());
        paymentCard.setSeriesCode(paymentCardDTO.getSeriesCode());
        return paymentCard;
    }

    private ProfileInfo createProfileInfo(Channel channel) {
        ProfileInfo profileInfo = new ProfileInfo();
        UniqueID uniqueID = new UniqueID();
        uniqueID.setID(channel.getIataNumber());
        uniqueID.setType(CONFIRM_TYPE);
        uniqueID.setIDContext(Constant.CONTEXT_IATA);
        profileInfo.getUniqueID().add(uniqueID);
        return profileInfo;
    }

    private ArrayOfRoomStay translateRoomStays(HotelReservationDTO ds3HotelReservation) {
        ArrayOfRoomStay arrayOfRoomStay = createArrayOfRoomStay();
        RoomStay roomStay = createRoomStay();
        roomStay.setRoomTypes(translateDS3RoomType(ds3HotelReservation.getRoomStaysList().get(0).getRoomTypeCode()));
        roomStay.setRatePlans(translateDS3RatePlan(ds3HotelReservation.getRoomStaysList().get(0).getRatePlanCode()));
        roomStay.setGuestCounts(translateGuestCount(ds3HotelReservation.getRoomStaysList().get(0)));
        roomStay.setTimeSpan(translateTimeSpan(ds3HotelReservation.getRoomStaysList().get(0).getStayDateRange()));
        roomStay.setBasicPropertyInfo(translatePropertyInfo(ds3HotelReservation.getHotelCode()));
        arrayOfRoomStay.getRoomStay().add(roomStay);
        return arrayOfRoomStay;
    }

    private HotelReferenceGroup translatePropertyInfo(String hotelCode) {
        HotelReferenceGroup hotelReferenceGroup = createHotelReferenceGroup();
        hotelReferenceGroup.setHotelCode(hotelCode);
        return hotelReferenceGroup;
    }

    private DateTimeSpanType translateTimeSpan(StayDateRangeDTO stayDateRange) {
        DateTimeSpanType dateTimeSpanType = createDateTimeSpanType();
        dateTimeSpanType.setStart(stayDateRange.getCheckin());
        dateTimeSpanType.setEnd(stayDateRange.getCheckout());
        return dateTimeSpanType;
    }

    private ArrayOfGuestCount translateGuestCount(ReservationRoomStayDTO reservationRoomStayDTO) {
        ArrayOfGuestCount arrayOfGuestCount = createArrayOfGuestCount();
        GuestCount guestCount = new GuestCount();
        guestCount.setAgeQualifyingCode(10);
        guestCount.setCount(reservationRoomStayDTO.getAdultCount());
        arrayOfGuestCount.getGuestCount().add(guestCount);
        if (reservationRoomStayDTO.getChildCount() > 0) {
            GuestCount childrenCount = new GuestCount();
            childrenCount.setAgeQualifyingCode(8);
            childrenCount.setCount(reservationRoomStayDTO.getChildCount());
            arrayOfGuestCount.getGuestCount().add(childrenCount);
        }
        return arrayOfGuestCount;
    }

    private ArrayOfRatePlan translateDS3RatePlan(String ratePlanCode) {
        ArrayOfRatePlan arrayOfRatePlan = createArrayOfRatePlan();
        RatePlan ratePlan = createRatePlan();
        ratePlan.setRatePlanCode(ratePlanCode);
        arrayOfRatePlan.getRatePlan().add(ratePlan);
        return arrayOfRatePlan;
    }

    private ArrayOfRoomType translateDS3RoomType(String roomTypeCode) {
        ArrayOfRoomType arrayOfRoomType = createArrayOfRoomType();
        RoomType roomType = createRoomType();
        roomType.setRoomTypeCode(roomTypeCode);
        roomType.setNumberOfUnits(1);
        arrayOfRoomType.getRoomType().add(roomType);
        return arrayOfRoomType;
    }

    private ArrayOfResGuest translateResGuests(HotelReservationDTO ds3HotelReservation) {
        ArrayOfResGuest arrayOfResGuest = createArrayOfResGuest();
        CustomerDTO contactPerson = ds3HotelReservation.getRoomStaysList().get(0).getContactPersonsList().get(0);
        for (CustomerDTO customerDTO : ds3HotelReservation.getRoomStaysList().get(0).getGuestsList()) {
            ResGuest resGuest = createResGuest();
            resGuest.setProfiles(createProfileInfo(contactPerson, customerDTO));
            arrayOfResGuest.getResGuest().add(resGuest);
        }
        return arrayOfResGuest;
    }

    private ArrayOfProfileInfo createProfileInfo(CustomerDTO contactPerson, CustomerDTO customerDTO) {
        ArrayOfProfileInfo arrayOfProfileInfo = createArrayOfProfileInfo();
        ProfileInfo profileInfo = createProfileInfo();
        Profile profile = createProfile();
        profile.setCustomer(createCustomer(contactPerson, customerDTO));
        profileInfo.setProfile(profile);
        arrayOfProfileInfo.getProfileInfo().add(profileInfo);
        return arrayOfProfileInfo;
    }

    private Customer createCustomer(CustomerDTO contactPerson, CustomerDTO customerDTO) {
        Customer customer = createCustomer();
        customer.setPersonName(translatePersonName(customerDTO.getPersonName()));
        customer.setContactPerson(translateContactPerson(contactPerson.getPersonName()));
        customer.setAddress(translateAddress(contactPerson.getAddressesList()));
        if (CollectionUtils.isNotEmpty(contactPerson.getEmailsList())) {
            customer.setEmail(translateEmails(contactPerson.getEmailsList()));
        }
        if (CollectionUtils.isNotEmpty(contactPerson.getTelephonesList())) {
            customer.setTelephone(translateTelephone(contactPerson.getTelephonesList()));
        }
        return customer;
    }

    private TelephoneInfo translateTelephone(List<TelephoneDTO> telephonesList) {
        TelephoneInfo telephoneInfo = createTelephoneInfo();
        telephoneInfo.setPhoneNumber(telephonesList.get(0).getNumber());
        return telephoneInfo;
    }

    private String translateEmails(List<String> emailsList) {
        StringBuilder builder = new StringBuilder();
        for (String email : emailsList) {
            builder.append(email).append(" ");
        }
        return builder.toString();
    }

    private AddressInfo translateAddress(List<String> addressesList) {
        if (CollectionUtils.isEmpty(addressesList)) {
            return null;
        }
        AddressInfo addressInfo = createAddressInfo();
        addressInfo.getAddressLine().addAll(addressesList);
        return addressInfo;
    }

    private ContactPerson translateContactPerson(PersonNameDTO personName) {
        ContactPerson contactPerson = createContactPerson();
        contactPerson.setPersonName(translatePersonName(personName));
        return contactPerson;
    }

    private PersonName translatePersonName(PersonNameDTO personName) {
        PersonName name = createPersonName();
        name.setGivenName(personName.getGivenName());
        name.setSurname(personName.getSurname());
        return name;
    }
}
